/* Copyright 2007 Gearbox Software - http://www.gearboxsoft.com
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
     http:www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.*/
namespace GearBlog.Web.Utils
{
	using System;
	using System.Collections.Specialized;
	using System.Globalization;
	using System.IO;
	using System.Net;
	using System.Text.RegularExpressions;
	using System.Web;
	using Castle.MonoRail.Framework;
	using GearBlog.Web.Helpers;
	using GearBlog.Web.Models;

	public class TrackBackUtil
	{
		/// <summary>
		/// Scan all links referred in post.body, then attempt to post a trackback for each link
		/// </summary>
		/// <param name="post"></param>
		/// <param name="context"></param>
		public static void Post(Post post, IRailsEngineContext context)
		{

			StringCollection links = ExtractUrls(ETextHelper.Textilize(post.Body, context));

			string permaLink = PermaLinkUtil.GetPermaLink(post.Id, context);
			foreach (string s in links)
			{
				SubmitTrackBack(s, post, permaLink);
			}


		}

	

		private static bool SubmitTrackBack(string url, Post post, string permaLink)
		{
			string trackBackPostUrl = GetTrackBackPostUrl(url);

			if (!string.IsNullOrEmpty(trackBackPostUrl))
			{
				if (!trackBackPostUrl.ToLower(CultureInfo.InvariantCulture).StartsWith("http://"))
				{
					trackBackPostUrl = "http://" + trackBackPostUrl;
				}

				string parameters = string.Format("title={0}&url={1}&blog_name={2}&excerpt={3}",
				                                  HttpUtility.HtmlEncode(post.Title),
				                                  HttpUtility.HtmlEncode(permaLink),
				                                  HttpUtility.HtmlEncode(Setting.Get().Title),
				                                  HttpUtility.HtmlEncode(post.GetBodySummary(1, 50))
					);

				Uri trackBackUrl = TryParseUri(trackBackPostUrl);
				if (trackBackUrl != null)
					return SendPing(trackBackUrl, parameters);
				else
					return false;
			}
			else
				return false;	
		}
		private static Uri TryParseUri(string uri)
		{
			try
			{
				return new Uri(uri);

			}
			catch (UriFormatException)
			{
				return null;
			}
		}

		private static bool SendPing(Uri trackBackItem, string parameters)
		{
			HttpWebRequest request = HttpUtil.CreateRequest(trackBackItem);
			request.Method = "POST";
			request.ContentLength = parameters.Length;
			request.ContentType = "application/x-www-form-urlencoded";
			request.KeepAlive = false;
			

			using (StreamWriter myWriter = new StreamWriter(request.GetRequestStream()))
			{
				myWriter.Write(parameters);
			}

			HttpWebResponse response = (HttpWebResponse)request.GetResponse();

			return (response.StatusCode == HttpStatusCode.OK);
		}
		private static StringCollection ExtractUrls(string text)
		{
			StringCollection c=new StringCollection();
			MatchCollection mc = Regex.Matches(text, @"href(\s*)=\s*""?(?<url>(https?://)?\w+[\w\.-]*(:\d{1,5})?/?([\w./-]+)?(\?[\w.&=-]+)?)""?",
			              RegexOptions.IgnoreCase);

			foreach (Match match in mc)
			{
				c.Add(match.Groups["url"].Value);
			}
			
			return c;


		}

		/// <summary>
		/// Find track back url from rdf tag. Source from SubText
		/// http://subtextproject.com
		/// </summary>
		/// <param name="trackBackUrl">Url for the page contains rdf info on track back</param>
		/// <returns></returns>
		private static string GetTrackBackPostUrl(string trackBackUrl)
		{
			string trackBackPageText = HttpUtil.GetPageText(new Uri(trackBackUrl));
			if (!Regex.IsMatch(trackBackPageText, trackBackUrl, RegexOptions.IgnoreCase | RegexOptions.Singleline))
			{
				string sPattern = @"<rdf:\w+\s[^>]*?>(</rdf:rdf>)?";
				Regex r = new Regex(sPattern, RegexOptions.IgnoreCase);
				Match m;

				for (m = r.Match(trackBackPageText); m.Success; m = m.NextMatch())
				{
					if (m.Groups.ToString().Length > 0)
					{
						string text = m.Groups[0].ToString();
						
						string tbPattern = "trackback:ping=\"([^\"]+)\"";
						Regex reg = new Regex(tbPattern, RegexOptions.IgnoreCase);
						Match m2 = reg.Match(text);
						if (m2.Success)
						{
							return m2.Result("$1");
						}

					}
				}
				// no match found
				return null;
			}
			return null;
		}
		

	}
}
